#include <condition_variable>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
using namespace std;

const int BUFFER_SIZE = 5;
std::queue<int> Q;
mutex mtx;
condition_variable conP, conC;

void producer(int seed) {
    srand(seed);
    while (1) {
        unique_lock<mutex> ulck(mtx);
        while (Q.size() == BUFFER_SIZE) { conP.wait(ulck); }
        int data = rand() % 100;
        Q.push(data);
        cout << this_thread::get_id() << " produced goods: " << data << endl;
        conC.notify_one();
        ulck.unlock();
        this_thread::sleep_for(chrono::seconds(3));
    }
}

void consumer() {
    while (1) {
        unique_lock<mutex> ulck(mtx);
        while (Q.empty()) { conC.wait(ulck); }
        int data = Q.front();
        Q.pop();
        cout << this_thread::get_id() << " consumed goods: " << data << endl;
        conP.notify_one();
        ulck.unlock();
        this_thread::sleep_for(chrono::seconds(3));
    }
}

int main() {
    std::thread p1(producer, rand() % 20);
    std::thread p2(producer, rand() % 20);
    std::thread p3(producer, rand() % 20);
    std::thread c1(consumer);
    p1.join();
    p2.join();
    p3.join();
    c1.join();
    return 0;
}